# 导入函数库
from jqdata import *

# 在策略里新增以下代码 diy_trade_v3.31 --------------------------------------------------------
import socket
import struct
import time
import json
import datetime as dt
IP_PORT = ('127.0.0.1', 8888)
transdir_flag = 1
def send_it(orders):
    if not orders:
        return
    if orders.action == 'open':
        action = 'buy'
    else:
        action = 'sell'
    get_now = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    trade_time = orders.add_time.strftime("%Y-%m-%d %H:%M:%S")
    Token = 123
    trade1 = [{'strategy':'MA1','idx':1,'time':get_now,'action': action,'zqdm': orders.security, 'qty': orders.amount, 'price': orders.price, 'trade_time':trade_time,'token':Token}]
    content = json.dumps(trade1)
    if transdir_flag:
        conn = socket.socket(socket.AF_INET,  socket.SOCK_STREAM)
        ret = conn.connect_ex(IP_PORT)  #连接服务端端口
        if ret==0:
            Data = bytes(content,'utf-8')
            DataLen = len(Data)
            Args = bytes('', "utf-8")
            ArgsLen = len(Args)
            Type = 13
            req = struct.pack('<BHH', Type, DataLen, ArgsLen) + bytes(Data) + Args
            conn.send(req)
            time.sleep(0.1)
            conn.close()
        else:
            print("conn failture")
            
def push_order_target(func):
    """
    继承order_target对象 百分比
    """

    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        if result == None:
            return
        send_it(result)
        return result
    return wrapper


def push_order_value(func):
    """
    继承order_value对象 数量
    """

    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs) 
        if result == None:
            return
        send_it(result)
        return result
    return wrapper

def push_order(func):
    """
    继承order对象 数据交易函数
    """

    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        if result == None:
            return
        send_it(result)
        return result
    return wrapper
 
def push_order_target_value(func):
    """
    继承order_target_value对象 数量
    """ 
    def wrapper(*args, **kwargs):   
        result = func(*args, **kwargs) 
        if result == None:
            return
        send_it(result)
        return result
    return wrapper
    

order = push_order(order)
order_target = push_order_target(order_target)
order_value = push_order_value(order_value)
order_target_value = push_order_target_value(order_target_value)
# 结束新增代码 diy_trade_v3.31 --------------------------------------------------------

# 初始化函数，设定基准等等
def initialize(context):
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    # 输出内容到日志 log.info()
    log.info('初始函数开始运行且全局只运行一次')
    # 过滤掉order系列API产生的比error级别低的log
    # log.set_level('order', 'error')

    ### 股票相关设定 ###
    # 股票类每笔交易时的手续费是：买入时佣金万分之三，卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')

    ## 运行函数（reference_security为运行时间的参考标的；传入的标的只做种类区分，因此传入'000300.XSHG'或'510300.XSHG'是一样的）
      # 开盘前运行
    run_daily(before_market_open, time='before_open', reference_security='000300.XSHG')
      # 开盘时运行
    run_daily(market_open, time='10:30', reference_security='000300.XSHG')
      # 收盘后运行
    run_daily(after_market_close, time='after_close', reference_security='000300.XSHG')

## 开盘前运行函数
def before_market_open(context):
    # 输出运行时间
    log.info('函数运行时间(before_market_open)：'+str(context.current_dt.time()))

    # 给微信发送消息（添加模拟交易，并绑定微信生效）
    # send_message('美好的一天~')

    # 要操作的股票：平安银行（g.为全局变量）
    g.security = '002241.XSHE'

## 开盘时运行函数
def market_open(context):
    log.info('函数运行时间(market_open):'+str(context.current_dt.time()))
    security = g.security
    # 获取股票的收盘价
    close_data = get_bars(security, count=5, unit='1d', fields=['close'])
    # 取得过去五天的平均价格
    MA5 = close_data['close'].mean()
    # 取得上一时间点价格
    current_price = close_data['close'][-1]
    # 取得当前的现金
    cash = context.portfolio.available_cash

    # 如果上一时间点价格高出五天平均价1%, 则全仓买入
    if (current_price > 1.01*MA5) and (cash > 0):
        # 记录这次买入
        log.info("价格高于均价 1%%, 买入 %s" % (security))
        print("当前可用资金为{0}, position_value为{0}".format(cash, context.portfolio.positions_value))
        # 用所有 cash 买入股票
        
        order_value(security, cash)

            
    # 如果上一时间点价格低于五天平均价, 则空仓卖出
    elif current_price < MA5 and context.portfolio.positions[security].closeable_amount > 0:
        # 记录这次卖出
        log.info("价格低于均价, 卖出 %s" % (security))
        # 卖出所有股票,使这只股票的最终持有量为0
        
        order_target(security, 0)
            

## 收盘后运行函数
def after_market_close(context):
    log.info(str('函数运行时间(after_market_close):'+str(context.current_dt.time())))
    #得到当天所有成交记录
    trades = get_trades()
    for _trade in trades.values():
        log.info('成交记录：'+str(_trade))
    log.info('一天结束')
    log.info('##############################################################')